package net.siufung.mybatis.metaobject;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * mybatis通用字段数据映射控制器
 * @author 陈建峰
 * @since 2021/11/12 2:38 下午
 */
@Slf4j
@AllArgsConstructor
public class MybatisMetaObjectHandler implements MetaObjectHandler {

    private final MybatisMetaObjectService mybatisPlusMetaObjectService;

    @Override
    public void insertFill(MetaObject metaObject) {

        String createdBy = StrUtil.toCamelCase(Constants.CREATED_BY);
        boolean createdByOf = metaObject.hasSetter(createdBy);
        if(createdByOf){
            this.strictInsertFill(metaObject, createdBy, String.class,
                    mybatisPlusMetaObjectService.getCurrentUserId());
        }

        String createdDept = StrUtil.toCamelCase(Constants.CREATED_DEPT);
        boolean createdDeptOf = metaObject.hasSetter(createdDept);
        if(createdDeptOf){
            this.strictInsertFill(metaObject, createdDept, String.class,
                    mybatisPlusMetaObjectService.getCurrentDeptId());
        }

        boolean createDateOf = metaObject.hasSetter(Constants.CREATED_AT);
        if(createDateOf){
            this.strictInsertFill(metaObject, Constants.CREATED_AT, LocalDateTime.class,
                    mybatisPlusMetaObjectService.getNow());
        }

        boolean versionOf = metaObject.hasSetter(Constants.VERSION);
        if(versionOf){
            this.strictInsertFill(metaObject, Constants.VERSION, Integer.class, 0);
        }

        boolean deleteOf = metaObject.hasSetter(Constants.DELETED);
        if(deleteOf){
            this.strictInsertFill(metaObject, Constants.DELETED, Boolean.class,false);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        /* updateBy 更新人*/
        boolean updateByOf = metaObject.hasSetter(Constants.UPDATED_BY);
        if(updateByOf){
            this.strictUpdateFill(metaObject, Constants.UPDATED_BY, String.class,
                    mybatisPlusMetaObjectService.getCurrentUserId());
        }
        /* updateDate 更新时间*/
        boolean updateDateOf = metaObject.hasSetter(Constants.UPDATED_AT);
        if(updateDateOf){
            this.strictUpdateFill(metaObject, Constants.UPDATED_AT, LocalDateTime.class,
                    mybatisPlusMetaObjectService.getNow());
        }
    }

    @Override
    public MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) {
        if (getFieldValByName(fieldName, metaObject) == null
                || StrUtil.equals(fieldName, Constants.UPDATED_AT)
                || StrUtil.equals(fieldName, Constants.UPDATED_BY)) {
            setFieldValByName(fieldName, fieldVal, metaObject);
        }
        return this;
    }

    @Override
    public MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {
        if (metaObject.getValue(fieldName) == null
                || StrUtil.equals(fieldName, Constants.UPDATED_AT)
                || StrUtil.equals(fieldName, Constants.UPDATED_BY)) {
            Object obj = fieldVal.get();
            if (Objects.nonNull(obj)) {
                metaObject.setValue(fieldName, obj);
            }
        }
        return this;
    }

    /**
     *
     */
    public static class Constants {

        /**
         * 版本号
         */
        public static final String VERSION = "version";

        /**
         * 创建人
         */
        public static final String CREATED_BY = "created_by";

        /**
         * 创建组
         */
        public static final String CREATED_DEPT = "created_dept";

        /**
         * 创建时间
         */
        public static final String CREATED_AT = "createdAt";

        /**
         * 更新人
         */
        public static final String UPDATED_BY = "updatedBy";

        /**
         * 更新时间
         */
        public static final String UPDATED_AT = "updatedAt";

        /**
         * 数据标识
         */
        public static final String DELETED = "deleted";

    }


}
